home *** CD-ROM | disk | FTP | other *** search
/ Aminet 8 / Aminet 8 (1995)(GTI - Schatztruhe)[!][Oct 1995].iso / Aminet / dev / gcc / gcc270_src.lha / gcc-2.7.0-amiga / amigasup.c < prev    next >
C/C++ Source or Header  |  1995-08-24  |  6KB  |  172 lines

  1. /* Supplementary host support for AmigaDOS.  Used only when host is AmigaDOS.
  2.    Copyright (C) 1994 Free Software Foundation, Inc.
  3.  
  4. This file is part of GNU CC.
  5.  
  6. GNU CC is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2, or (at your option)
  9. any later version.
  10.  
  11. GNU CC is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GNU CC; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  
  20. This code segment will interface between the startup code and the user's
  21. main(), adjusting the stack if necessary. Two entry points are provided,
  22. main(), and stkexit(). Programs should be compiled using
  23.     gcc -Dmain=stkmain -Dexit=stkexit
  24. and linked with this module.  Calling _exit is not provided for, but should
  25. be trivial to implement.
  26.  
  27. The minimum acceptable stack size is obtained from the environment variable
  28. GCC_STACK (change the #define ENVNAME to customize). If this variable is
  29. not defined, the default is 50000 bytes (change the #define SIZE to
  30. customize). If the current stack size is less than the minimum acceptable,
  31. then a new stack is allocated, and appropriate actions are taken to ensure
  32. that the original stack is restored before exit.
  33.  
  34. To link with my stderrfix hack, you will need to compile it using
  35.        gcc -Dmain=stkmain -c stderrfix.c
  36. and compile everything else (apart from this file) using
  37.        gcc -Dmain=mymain -Dexit=stkexit
  38. (I have not tested this, but there is no reason why it shouldn't work.)
  39.  
  40. AUTHOR:     Kriton Kyrimis (kyrimis@theseas.ntua.gr)
  41. KNOWN BUGS: Calling stkexit(0x8000000) will cause the program to exit
  42.             with the wrong exit code (0).
  43. DISCLAIMER: Use this code at your own risk.
  44. */
  45.  
  46. /* Putting this in version.c seems to screw up configure, which attempts to
  47.    extract the version number with a sed command that doesn't take this
  48.    string into account.  Also, don't include the date of compilation
  49.    in this string because the annoyance of not being able to do multistage
  50.    build comparisons across days is more than the convenience gained
  51.    (if any) by having the build date incoporated in the executables. -fnf */
  52. char VERSION[]="$VER:gcc 2.6.4";
  53.  
  54. #undef main
  55. #undef exit
  56.  
  57. #include <stdlib.h>
  58. #include <setjmp.h>
  59. #include <dos/dosextens.h>
  60. #include <proto/exec.h>
  61. #include <proto/dos.h>
  62.  
  63. #define SIZE 50000
  64. #define ENVNAME "GCCSTACK"
  65.  
  66. #define MAGIC 0x80000000
  67.  
  68. void stkexit(int);
  69.  
  70. static jmp_buf jmp;
  71. static int swapped = 0;
  72.  
  73. main(int argc, char **argv)
  74. {
  75.   /* Declare all variables as static, so that they are available no matter
  76.      which stack is active */
  77.   static struct Process *p;
  78.   static struct CommandLineInterface *c;
  79.   static int stacksize, prefsize, status;
  80.   static struct StackSwapStruct stack;
  81.   static char *envsize, *newstack;
  82.   /* The next two variables point to information in the old stack. Declare
  83.      them volatile, to avoid unexpected surprises introduced by the optimizer.
  84.      (This is apparently unnecessary under 2.6.1, but you never know.) */
  85.   static volatile int myargc;
  86.   static volatile char **myargv;
  87.  
  88.   /* Determine original stack size */
  89.   p = (struct Process *)FindTask(NULL);
  90.   c = BADDR(p->pr_CLI);
  91.   if (c) {
  92.     stacksize = c->cli_DefaultStack * sizeof(LONG);
  93.   }else{
  94.     stacksize = p->pr_StackSize;
  95.   }
  96.  
  97.   /* Determine preferred stack size */
  98.   envsize = getenv(ENVNAME);
  99.   if (envsize) {
  100.     prefsize = atoi(envsize);
  101.   }else{
  102.     prefsize = SIZE;
  103.   }
  104.  
  105.   myargc = argc;
  106.   myargv = argv;
  107.  
  108.   if (prefsize > stacksize) {
  109.     /* Round size to next long word */
  110.     prefsize = ((prefsize + (sizeof(LONG) - 1)) / sizeof(LONG)) * sizeof(LONG);
  111.  
  112.     /* Allocate new stack */
  113.     newstack = malloc(prefsize);
  114.     if (!newstack) {
  115.       Printf("Can't allocate new stack!\n");
  116.       exit(RETURN_FAIL);
  117.     }
  118.  
  119.     /* Build new stack structure */
  120.     stack.stk_Lower = newstack;
  121.     stack.stk_Upper = (ULONG)newstack + prefsize;
  122.     /* Determine the address the stackpointer has to go:
  123.      * Point to the last longword of the stackframe and subtract
  124.      * the arguments of StackSwap() since the compiler might
  125.      * try to adjust the stackpointer after calling it :-(.
  126.      */
  127.     stack.stk_Pointer = (APTR)(stack.stk_Upper-2*sizeof(long));
  128.  
  129.     /* Switch to new stack */
  130.     StackSwap(&stack);
  131.     swapped = 1;
  132.     if (c) {
  133.       c->cli_DefaultStack = prefsize / sizeof(LONG);
  134.     }
  135.  
  136.     /* Save the current position, so that on exit we may return to the exact
  137.        stack depth where we switched stacks, and switch them back again.
  138.        Programs should invoke stkexit() rather than exit(), or return from
  139.        stkmain(). Status contains the exit status given to stkexit().*/
  140.     if ((status = setjmp(jmp)) != 0) {
  141.       /* Switch back to old stack before exiting */
  142.       StackSwap(&stack);
  143.       if (c) {
  144.     c->cli_DefaultStack = stacksize / sizeof(LONG);
  145.       }
  146.       free(newstack);
  147.       if (status == MAGIC) {    /* If real exit status is 0, stkexit converts */
  148.         status = 0;        /* it to MAGIC, to avoid confusing setjmp */
  149.       }
  150.       exit(status);
  151.     }
  152.     status = stkmain(myargc, myargv);
  153.     stkexit(status);
  154.   } else {
  155.     return stkmain(myargc, myargv);
  156.   }
  157. }
  158.  
  159. void
  160. stkexit(int status)
  161. {
  162.   if (!swapped) {
  163.     exit (status);
  164.   } else {
  165.     if (status == 0) {    /* The world will end iff we pass 0 as the value */
  166.       status = MAGIC;    /* for longjmp */
  167.     }
  168.     longjmp(jmp, status);
  169.   }
  170. }
  171.  
  172.